package com.murong.ai.chat.config;

import ai.picovoice.leopard.Leopard;
import ai.picovoice.porcupine.Porcupine;
import lombok.SneakyThrows;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;

import javax.sound.sampled.*;
import java.io.File;
import java.util.Arrays;

@Configuration
public class ChatAutoConfiguration {

    @Bean
    @SneakyThrows
    public Porcupine porcupine(Environment environment, ResourceLoader resourceLoader){
        String accessKey=environment.getProperty("porcupine.access.key");

        String keywordFilePath = environment.getProperty("porcupine.keyword.file.path");
        Resource resource = resourceLoader.getResource(keywordFilePath);
        File[] files = resource.getFile().listFiles();
        String[] keywordPaths = Arrays.stream(files)
                .map(File::getAbsolutePath).toArray(String[]::new);

        float[] floats = new float[keywordPaths.length];
        for (int i = 0; i < keywordPaths.length; i++) {
            floats[i] = 0.5f;
        }

        return new Porcupine.Builder().setAccessKey(accessKey)
                .setKeywordPaths(keywordPaths)
                .setSensitivities(floats)
                .build();
    }

    @Bean
    public AudioFormat audioFormat(Porcupine porcupine){
        return new AudioFormat(porcupine.getSampleRate(), 16, 1, true, false);
    }

    @Bean
    public DataLine.Info info(AudioFormat audioFormat){
        return new DataLine.Info(TargetDataLine.class, audioFormat);
    }

    @Bean
    public TargetDataLine targetDataLine(Environment environment,DataLine.Info info) {
        Integer deviceIndex=environment.getProperty("speech.audio.device.index",Integer.class);
        if (deviceIndex >= 0) {
            try {
                Mixer.Info mixerInfo = AudioSystem.getMixerInfo()[deviceIndex];
                Mixer mixer = AudioSystem.getMixer(mixerInfo);
                if (mixer.isLineSupported(info)) {
                    return (TargetDataLine) mixer.getLine(info);
                } else {
                    System.err.printf("Audio capture device at index %s does not support the audio format required by " +
                                    "Picovoice. Using default capture device.", deviceIndex);
                }
            } catch (Exception e) {
                System.err.printf("No capture device found at index %s. Using default capture device.", deviceIndex);
            }
        }
        return getDefaultCaptureDevice(info);
    }

    @SneakyThrows
    @Bean
    public Leopard leopard(Environment environment) {
        String accessKey=environment.getProperty("porcupine.access.key");
      return new Leopard.Builder().setAccessKey(accessKey).build();
    }

    @SneakyThrows
    private TargetDataLine getDefaultCaptureDevice(DataLine.Info dataLineInfo){
        if (!AudioSystem.isLineSupported(dataLineInfo)) {
            throw new LineUnavailableException("Default capture device does not support the audio " +
                    "format required by Picovoice (16kHz, 16-bit, linearly-encoded, single-channel PCM).");
        }
        return (TargetDataLine) AudioSystem.getLine(dataLineInfo);
    }
}
